home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / calc.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  6KB  |  222 lines

  1. /*
  2.  * A very simple 16-bit TSR (POP-UP) calculator, featuring automatic entry
  3.  * of last result into DOS applications. This feature works only on AT or
  4.  * higher class machines with a recent BIOS.
  5.  * 
  6.  * Use 'calc' with no operands for NON-TSR operation.
  7.  * 
  8.  * If HOTKEYS are specified on the command line, CALC will install
  9.  * itself as a TSR (Ram-Resident) program, which can be invoked at
  10.  * any time by pressing the HOTKEYS. Available HOTKEYS are:
  11.  *         L - Left SHIFT
  12.  *         R - Right SHIFT
  13.  *         A - ALT
  14.  *         C - CONTROL
  15.  *         S - SysRq (Caution: some systems may not like this one)
  16.  * 
  17.  *     eg: CALC LR    (Install with LEFT+RIGHT SHIFT for hotkeys)
  18.  * 
  19.  * Keys used:
  20.  *     +        Addition
  21.  *     -        Subtraction
  22.  *     *        Multiply
  23.  *     /        Divide
  24.  *     %        Modulus
  25.  *     &        Bitwise AND
  26.  *     |        Bitwise OR
  27.  *     ^        Bitwise EXCLUSIVE OR
  28.  *     <        Shift left
  29.  *     >        Shift right
  30.  *     =        Display result
  31.  *     0-9        Decimal input digits
  32.  *     A-F        Hexidecimal input digits
  33.  *     'c        Enter a single ASCII character value
  34.  *     "cc        Enter a dual ASCII character value
  35.  *     K        Clear display
  36.  *     R        Read value from memory
  37.  *     S        Store value in memory
  38.  *     BKSP    Clear last digit
  39.  *     SPACE    Toggle HEX/DECIMAL
  40.  *     ESC        Exit, no entry
  41.  *     ENTER    Exit, enter value to DOS application (works only on AT or higher)
  42.  *     UP        Move display up
  43.  *     DOWN    Move display down
  44.  *     RIGHT    Move display right
  45.  *     LEFT    Move display left
  46.  *
  47.  * Copyright 1990-1994 Dave Dunfield
  48.  * All rights reserved.
  49.  *
  50.  * Permission granted for personal (non-commercial) use only.
  51.  *
  52.  * Compile command: cc calc -fop
  53.  */
  54. #include <stdio.h>
  55. #include <window.h>
  56. #include <tsr.h>
  57.  
  58.     int x=33, y=10, acc = 0, acc1, memory = 0;
  59.     char op, mode = 0;
  60.  
  61.     /* Scan codes for entered digit values */
  62.     char scans[] = {
  63.         0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  64.         0x09, 0x0A, 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21 };
  65.  
  66. /*
  67.  * Main calculator program
  68.  */
  69. calc()
  70. {
  71.     char c, buffer[7];
  72.  
  73.     op = acc ? '=' : ' ';        /* Use '=' reset mode if value left over */
  74.  
  75. redraw:
  76.     wopen(x, y, 9, 4, (WSAVE|WBOX2|WCOPEN|WSCROLL)+REVERSE);
  77.     wcursor_off();
  78.     for(;;) {
  79.         wprintf(mode ? "\r%c $%04x" : "\r%c%6d", op, acc);
  80.         switch(c = toupper(wgetc())) {
  81.             case '+' :        /* Record all operators */
  82.             case '-' :
  83.             case '*' :
  84.             case '/' :
  85.             case '%' :
  86.             case '&' :
  87.             case '|' :
  88.             case '^' :
  89.             case '<' :
  90.             case '>' :
  91.                 doeval();
  92.                 wprintf(mode ? "\r  $%04x\n" : "\r %6d\n", acc1);
  93.                 acc = 0;
  94.                 op = c;
  95.                 break;
  96.             case '=' :        /* Display partial result */
  97.                 doeval();
  98.                 wclwin();
  99.                 acc = acc1;
  100.                 op = '=';
  101.                 break;
  102.             case '\'' :        /* Single ASCII character */
  103.                 acc = wgetc();
  104.                 break;
  105.             case '"' :        /* Double ASCII character */
  106.                 acc = (wgetc() << 8) | wgetc();
  107.                 break;
  108.             case _KBS :        /* Delete last entered digit */
  109.                 acc /= mode ? 16 : 10;
  110.                 break;
  111.             case _KUA :        /* Move display up */
  112.                 if(y) --y;
  113.                 goto move;
  114.             case _KDA :        /* Move display down */
  115.                 if(y < 21) ++y;
  116.                 goto move;
  117.             case _KLA :        /* Move display left */
  118.                 if(x) --x;
  119.                 goto move;
  120.             case _KRA :        /* Move display right */
  121.                 if(x < 71)
  122.                     ++x;
  123.             move:
  124.                 wclose();
  125.                 goto redraw;
  126.             case ' ' :        /* Toggle hex/decmal mode */
  127.                 mode = !mode;
  128.                 break;
  129.             case '\n' :        /* Exit and enter value */
  130.                 doeval();
  131.                 sprintf(buffer, mode ? "%x" : "%d", acc = acc1);
  132.                 for(acc1 = 0; c = buffer[acc1]; ++acc1)
  133.                     pushkey(c, scans[c]);
  134.                 wclose();
  135.                 return;
  136.             case '\x1B' :    /* Exit and don't enter value */
  137.                 doeval();
  138.                 acc = acc1;
  139.                 wclose();
  140.                 return;
  141.             case 'K' :        /* Clear the calculator display */
  142.                 acc = acc1 = 0;
  143.                 op = ' ';
  144.                 break;
  145.             case 'S' :        /* Save to memory */
  146.                 memory = acc;
  147.                 break;
  148.             case 'R' :        /* Restore from memory */
  149.                 acc = memory;
  150.                 break;
  151.             default:
  152.                 if(op == '=') {        /* Previous result to clear */
  153.                     acc = acc1 = 0;
  154.                     op = ' '; }
  155.                 if(mode) {                /* Hex input */
  156.                     if(isdigit(c))
  157.                         acc = (acc * 16) + (c - '0');
  158.                     else if((c >= 'A') && (c <= 'F'))
  159.                         acc = (acc * 16) + (c - ('A'-10)); }
  160.                 else if(isdigit(c))        /* Decimal input */
  161.                     acc = (acc * 10) + (c - '0'); } }
  162. }
  163.  
  164. /*
  165.  * Evaluate the last recorded operation
  166.  */
  167. doeval()
  168. {
  169.     switch(op) {
  170.         case '+' : acc1 += acc; break;
  171.         case '-' : acc1 -= acc; break;
  172.         case '*' : acc1 *= acc; break;
  173.         case '/' : if(!acc) goto dbz; acc1 /= acc; break;
  174.         case '%' : if(!acc) goto dbz; acc1 %= acc; break;
  175.         case '&' : acc1 &= acc; break;
  176.         case '|' : acc1 |= acc; break;
  177.         case '^' : acc1 ^= acc; break;
  178.         case '<' : acc1 <<=acc; break;
  179.         case '>' : acc1 >>=acc; break;
  180.         default  : acc1 = acc; break;
  181.         dbz: wprintf("\n? / 0\nError"); wgetc(); }
  182. }
  183.  
  184. /*
  185.  * Shove a key (char & scancode) into the BIOS keyboard buffer
  186.  */
  187. pushkey(c, s) asm
  188. {
  189.         MOV        CH,4[BP]        ; Get Scan code
  190.         MOV        CL,6[BP]        ; Get character
  191.         MOV        AH,05h            ; Push key...
  192.         INT        16h                ; Ask BIOS
  193. }
  194.  
  195. /*
  196.  * Main program, either TSR or execute main tty program menu
  197.  */
  198. main(argc, argv)
  199.     int argc;
  200.     int *argv[];
  201. {
  202.     int hot_keys;
  203.     char *ptr;
  204.  
  205. /* If RAM-resident, print startup message & TSR */
  206.     if(argc > 1) {
  207.         fputs("POP-UP Calculator\n\nCopyright 1990-1994 Dave Dunfield\nAll rights reserved.", stderr);
  208.         hot_keys = 0;
  209.         ptr = argv[1];
  210.         while(*ptr) switch(toupper(*ptr++)) {
  211.             case 'A' : hot_keys |= ALT;        break;
  212.             case 'C' : hot_keys |= CONTROL;    break;
  213.             case 'L' : hot_keys |= L_SHIFT;    break;
  214.             case 'R' : hot_keys |= R_SHIFT; break;
  215.             case 'S' : hot_keys |= SYS_REQ;    break;
  216.             default: abort("\n\nInvalid HOTKEY"); }
  217.         tsr(&calc, hot_keys, 2000); }
  218.  
  219. /* Not RAM-resident, execute the program */
  220.     calc();
  221. }
  222.